<?php

App::uses('RequestFacade', 'Network');
App::uses('WeixinCompUtility', 'Utility');

/**
 * 微信相关操作
 * 扩展的Utility类名后面都加上Utility，防止类名与Model等其它类重名
 * @author Arlon
 *
 */
class WeixinUtility {
	
	public static $appId = '';
	public static $secretKey = '';
	
	public static $url = 'https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=%s';

	public static $menu_url = 'https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s';
	
	public static $user_url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s';
    
	public static $userinfo_url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token=%s&openid=%s&lang=zh_CN';
	
	public static $upload_url = 'https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s';
	
	public static function datacube($type,$begin_date,$end_date){
	    $access_token = self::getAccessToken();	    
	    $url = 'https://api.weixin.qq.com/datacube/'.$type.'?access_token='.$access_token;
	    $post_data = '{"begin_date":"'.$begin_date.'","end_date":"'.$end_date.'"}';
	    $response =  RequestFacade::post($url,$post_data);
	    return \json_decode($response->body,true);
	}
    /**
     * 发送文本客服消息
     * @param $touser 用户openid
     * @param $content  消息正文
     * @return object Response
     */
    public static function sendTextMsg($touser, $content,$access_token = '') {

    	if(empty($access_token)){
			$access_token = self::getAccessToken(false,true);
    	}

    	$url = sprintf(self::$url,$access_token);    	
    	$post_data = '{"touser":"'.$touser.'","msgtype":"text","text":{"content":"'.addslashes($content).'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    
    /**
     * 发送图片客服消息
     * @param $touser 用户openid
     * @param $media_id  图片资源编号
     * @return object Response
     */
    public static function sendImageMsg($touser, $media_id,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"image","image":{"media_id":"'.$media_id.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    
    /**
     * 发送微信多图文素材客服消息
     * @param $touser 用户openid
     * @param $media_id  图片资源编号
     * @return object Response
     */
    public static function sendMpnewsMsg($touser, $media_id,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"mpnews","mpnews":{"media_id":"'.$media_id.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    /**
     * 发送卡券客服消息
     * @param $touser 用户openid
     * @param $media_id  图片资源编号
     * @return object Response
     */
    public static function sendCardMsg($touser, $media_id,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"wxcard","wxcard":{"media_id":"'.$media_id.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    /**
     * 发送语音客服消息
     * @param $touser 用户openid
     * @param $media_id  图片资源编号
     * @return object Response
     */
    public static function sendVoiceMsg($touser, $media_id,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"voice","voice":{"media_id":"'.$media_id.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    /**
     * 发送视频客服消息
     * @param $touser 用户openid
     * @param $media_id  图片资源编号
     * @return object Response
     */
    public static function sendVideoMsg($touser, $media_id,$title,$description,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"video","video":{"media_id":"'.$media_id.'","title":"'.$title.'","description":"'.$description.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    /**
     * 发送视频客服消息
     * @param $touser 用户openid
     * @param $media_id  图片资源编号
     * @return object Response
     */
    public static function sendMusicMsg($touser, $media_id,$url,$title,$description,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"music","music":{"media_id":"'.$media_id.'","url":"'.$url.'","title":"'.$title.'","description":"'.$description.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    
    /**
     * 发送图文客服消息
     * @param $touser 用户openid
     * @param $articles  array 多维数组 { "title":"Happy Day", "description":"Is Really A Happy Day", "url":"URL", "picurl":"PIC_URL"  },
     * @return object Response
     */
    public static function sendArticleMsg($touser, $articles,$access_token = '') {
    
        if(empty($access_token)){
            $access_token = self::getAccessToken(false,true);
        }
    
        $url = sprintf(self::$url,$access_token);
        $post_data = '{"touser":"'.$touser.'","msgtype":"news","news":{"articles":"'.$articles.'"}}';
        $response =  RequestFacade::post($url,$post_data);
        return \json_decode($response->body,true);
    }
    
    
    /**
     * 设置公众号的菜单，
     * @param unknown $menus wx_menus表内容的数组
     */
    public static function createMenu($menus,$dev = false){
    	$json_arr = array();
    	foreach($menus as $item){
    		if(!empty($item['children'])){
    			$sub_menu = array('name'=>$item['WxMenu']['name']);
    			$sub_menu['sub_button'] = array();
    			foreach($item['children'] as $sub_item){
					if($sub_item['WxMenu']['type']=='click'){
    					$sub_menu['sub_button'][] = array('key'=>$sub_item['WxMenu']['slug'], 'type'=>$sub_item['WxMenu']['type'],'name'=>$sub_item['WxMenu']['name']);
					}
					elseif(in_array($sub_item['WxMenu']['type'],array('media_id','view_limited'))){
    						$sub_menu['sub_button'][] = array('media_id'=>$sub_item['WxMenu']['media_id'], 'type'=>$sub_item['WxMenu']['type'],'name'=>$sub_item['WxMenu']['name']);
					}
					else{
    					$sub_menu['sub_button'][] = array('url'=>$sub_item['WxMenu']['link'], 'type'=>$sub_item['WxMenu']['type'],'name'=>$sub_item['WxMenu']['name']);
					}
    			} 
    			$json_arr['button'][] = $sub_menu;
    		}
    		else{
				if($item['WxMenu']['type']=='click'){
	    				$json_arr['button'][] = array('key'=>$item['WxMenu']['slug'], 'type'=>$item['WxMenu']['type'],'name'=>$item['WxMenu']['name']);
				}
				elseif(in_array($item['WxMenu']['type'],array('media_id','view_limited'))){
    					$json_arr['button'][] = array('media_id'=>$item['WxMenu']['media_id'], 'type'=>$item['WxMenu']['type'],'name'=>$item['WxMenu']['name']);
				}
				else{
	    				$json_arr['button'][] = array('url'=>$item['WxMenu']['link'], 'type'=>$item['WxMenu']['type'],'name'=>$item['WxMenu']['name']);
				}
    		}    		
    	}
    	$json_menu =  json_encode($json_arr,JSON_UNESCAPED_UNICODE);

    	
    	return self::createMenuJson($json_menu,$dev);
    }
    
    public static function createMenuJson($json_menu,$dev = false) {
    	
    	$access_token = self::getAccessToken(false,$dev);
    	$menu_url = sprintf(self::$menu_url,$access_token);
    	$response =  RequestFacade::post($menu_url,$json_menu);
    	return \json_decode($response->body,true);
    }
    
    public static function getAutoReplyInfo(){
    	$access_token = self::getAccessToken();
    	$url = 'https://api.weixin.qq.com/cgi-bin/get_current_autoreply_info?access_token='.$access_token;
    	
    	$response =  RequestFacade::get($url);
    	return \json_decode($response->body,true);
    }
    
    public static function getCurrentMenu(){
    	
    	$access_token = self::getAccessToken();
    	$url = 'https://api.weixin.qq.com/cgi-bin/get_current_selfmenu_info?access_token='.$access_token;
    	$response =  RequestFacade::get($url);
    	return \json_decode($response->body,true);    	
    }
    
    public static function resetMenu($verify = true){
    	 $menu = self::getCurrentMenu();
    	 //if($menu['is_menu_open']) {
    	 
    	 if(!$verify) { // 未认证的公众号
    	     //print_r($menu);
    	     foreach($menu['selfmenu_info']['button'] as &$me) {
    	         if(!empty($me['sub_button'])) {
    	             foreach($me['sub_button']['list'] as &$item) {
    	                 if($item['type'] == 'view') {
    	                     $item['type'] = 'view_limited';
    	                     $item['media_id'] = '';
    	                     unset($item['url']);
    	                 }
    	                 elseif($item['type'] == 'click') {
    	                     $item['type'] = 'media_id';
    	                     $item['media_id'] = '';
    	                     unset($item['url']);
    	                 }
			             $me['sub_button'][] = $item;
    	             }
			         unset($me['sub_button']['list']);
    	         }
    	     }
    	     $json = json_encode($menu['selfmenu_info'],JSON_UNESCAPED_UNICODE);
    	 }
    	 else{
    	     foreach($menu['selfmenu_info']['button'] as &$me) {
    	         if(!empty($me['sub_button'])) {
			         $me['sub_button'] = $me['sub_button']['list'];
    	         }
    	     }
    	     $json = json_encode($menu['selfmenu_info'],JSON_UNESCAPED_UNICODE);
    	 }    	
    	 return self::createMenuJson($json);
//     	 }
//     	 else{
//     	 	return 0;
//     	 }
    }
    /**二维码类型，QR_SCENE为临时,QR_LIMIT_SCENE为永久,QR_LIMIT_STR_SCENE为永久的字符串参数值**/
    public static function qrcode_create($scene_id,$action='QR_SCENE'){
         
        $access_token = self::getAccessToken();
        $url = 'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token='.$access_token;
        
        if($action=='QR_SCENE') {
            $posts = array(
                'expire_seconds'=> 604800,
                "action_name"=> $action, 
                "action_info" => array("scene" => array('scene_id' => $scene_id )),
            );
        }
        else{
        	if($action == 'QR_LIMIT_SCENE'){
	            $posts = array(
	                "action_name"=> 'QR_LIMIT_SCENE',// "QR_LIMIT_SCENE", "QR_LIMIT_STR_SCENE",
	                "action_info" => array("scene" => array('scene_id' => $scene_id )),
	            );
        	}
        	else{
        		$posts = array(
        				"action_name"=> 'QR_LIMIT_STR_SCENE',// "QR_LIMIT_SCENE", "QR_LIMIT_STR_SCENE",
        				"action_info" => array("scene" => array('scene_str' => $scene_id )),
        		);
        	}
        }
        
        $json_data =  json_encode($posts,JSON_UNESCAPED_UNICODE);
        
        $response =  RequestFacade::post($url,$json_data);
        return \json_decode($response->body,true);
    }
    
    /**
     * 
     * @param unknown $paramArr see at http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1
     * @return unknown
     */
    public static function wxPrepay($paramArr,$secret) {
    	
    	$prepay_url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
    	
    	$paramArr['sign'] = $sign = self::getSignature($paramArr,$secret);
    	$xml = array_to_xml($paramArr);
    	$xml = str_replace('<?xml version="1.0" encoding="UTF-8"?>','',$xml);
    	
    	$result = RequestFacade::post($prepay_url,$xml);
    	
    	return $result;
    }
    
    
    public static function getWechatPayUrl($appid,$secret,$mch_id,$product_id,$nonce_str=''){
    	if(empty($nonce_str)) $nonce_str = strtolower(random_str(16));
    	$arr = array(
    		'appid' => $appid,
    		'mch_id' => $mch_id,    		
    		'nonce_str' => $nonce_str,
    		'product_id' => $product_id,
    		'time_stamp' => time(),
    	);
    	$sign = self::getSignature($arr,$secret); 
    	
    	$url = 'weixin://wxpay/bizpayurl?'.http_build_query( $arr ).'&sign='.$sign;
    	//echo "=====$appid,$secret====$url";exit;
    	return $url;
    }
    
    public static function getSignature($tmpArr=array(),$secKey = '')
	{
		ksort($tmpArr);
		$tmpStr = http_build_query( $tmpArr );
		$tmpStr = str_replace('%2F','/',$tmpStr);
		$tmpStr = str_replace('%25','%',$tmpStr);
		
		$signStr = $tmpStr.'&key='.$secKey;
		//echo "$signStr\n<br/>";
		return strtoupper(md5($signStr));
	}
	
	/**
	 * 增加永久图文
	 * @param unknown $articles
	 */
	public static function add_news($articles){
		if(empty($access_token)){
			$access_token = self::getAccessToken();
		}
		$i = 0;
		do{
    		$add_url = 'https://api.weixin.qq.com/cgi-bin/material/add_news?access_token='.$access_token;
    		$response =  RequestFacade::post($add_url,json_encode(array('articles'=>$articles),JSON_UNESCAPED_UNICODE));
    		$result = \json_decode($response->body,true);
    		$i ++;
		}while( empty($result) && $i < 3 );
		
		return $result;
	}
	
	/**
	 * 编辑永久图文
	 * @param unknown $articles
	 */
	public static function update_news($media_id,$index,$article){
	    if(empty($access_token)){
	        $access_token = self::getAccessToken();
	    }
	    if(empty($index)) $index = 0;
	    $update_url = 'https://api.weixin.qq.com/cgi-bin/material/update_news?access_token='.$access_token;
	    $response =  RequestFacade::post($update_url,json_encode(array('media_id' =>$media_id, 'index' => $index,'articles'=>$article),JSON_UNESCAPED_UNICODE));
	    return \json_decode($response->body,true);
	}
	
	
	public static function sendAll($media_id,$type='mpnews',$send_ignore_reprint = 1,$groupid= ''){
	    $access_token = self::getAccessToken();
	    if($access_token){
	       $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/sendall?access_token='.$access_token;
	       if($type=='news') $type = 'mpnews';
	       $posts = array(
	           "filter" => array(
	               "is_to_all" => !$groupid ? true: false,
	               "group_id" => $groupid
	           ),
	           $type => array( "media_id" => $media_id),
	           "msgtype" => $type,
	           "send_ignore_reprint" => $send_ignore_reprint,
	       );
	       $response =  RequestFacade::post($url,json_encode($posts,JSON_UNESCAPED_UNICODE));
	       return \json_decode($response->body,true);
	    }
	    else{
	        return array('errcode'=> 13501,'errmsg' => 'get access token error');
	    }
	}
	
	/**
	 * 消息预览
	 * @param unknown $media_id
	 * @param unknown $touser
	 * @param string $msgtype
	 */
	public static function preview($media_id,$touser,$msgtype='mpnews'){
	    $access_token = self::getAccessToken();
	    $url = 'https://api.weixin.qq.com/cgi-bin/message/mass/preview?access_token='.$access_token;
	    $response =  RequestFacade::post($url,json_encode(array( "touser"=>$touser, $msgtype=>array('media_id'=>$media_id), "msgtype"=>$msgtype )));
	    return \json_decode($response->body,true);
	}
	/**
	 * 获取素材总数
	 */
	public static function get_materialcount(){
		if(empty($access_token)){
			$access_token = self::getAccessToken();
		}
		$url = 'https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token='.$access_token;
		$response =  RequestFacade::get($url);		
		return \json_decode($response->body,true);
	}

	public static function getTempMedia($media_id,&$header = NULL){
		$access_token = self::getAccessToken();
		if(!empty($access_token)){
			$url = 'https://api.weixin.qq.com/cgi-bin/media/get?access_token='.$access_token.'&media_id='.$media_id;
			$response =  RequestFacade::get($url);	
			$numargs = func_num_args();
			if( $numargs == 2 ) {
				$header = $response->headers;
			}
			return $response->body;
		}
		else{
			return null;
		}
	}
	
	public static function getTmpMaterial($media_id,&$header = NULL) {
	    $access_token = self::getAccessToken();
	    $url = 'https://api.weixin.qq.com/cgi-bin/media/get?access_token='.$access_token.'&media_id='.$media_id;
	    $response =  RequestFacade::get($url);	     
	    $numargs = func_num_args();
	    if( $numargs == 2 ) {
	        $header = $response->headers;
	    }
	    return $response->body;
	}

//	public function getMeterialUrl($media_id){
//        $content = self::getMaterial($media_id);
//        $media_info = json_decode($content,true);
//
//    }
	
	public static function getMaterial($media_id,&$header = NULL) {
	    $access_token = self::getAccessToken();
	    $batch_url = 'https://api.weixin.qq.com/cgi-bin/material/get_material?access_token='.$access_token;
	    $response =  RequestFacade::post($batch_url,json_encode(array('media_id'=>$media_id)));
	    
	    $numargs = func_num_args();
		if( $numargs == 2 ) {
			$header = $response->headers;
		}
	    return $response->body;
	}

	/**
	 *新增视频永久素材
	 */
	public static function add_video($mediafile,$title,$introduction){
		if(empty($access_token)){
			$access_token = self::getAccessToken();
		}
		$batch_url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.$access_token;
		$response =  RequestFacade::post($batch_url,array('media'=> '@'.$mediafile,'type'=>'video','description'=>json_encode(array('title'=>$title,'introduction'=>$introduction))));
		return \json_decode($response->body,true);
	}
	

	/**
	 *新增其他类型永久素材
	 */
	public static function add_material($mediafile,$type='image'){


        $src_media = $mediafile;
		if(empty($access_token)){
			$access_token = self::getAccessToken();
		}
		$is_remote = false; $localfile = $cacke_key = '';
		if(strpos($mediafile,'http://') !==false || strpos($mediafile,'https://') !==false) {
		    
		    $cacke_key = 'media_id_'.self::$appId.'_'.$type.'_'.md5($mediafile); //对远程的网址内容才缓存media_id
		    $media_id = Cache::read($cacke_key,'long');		    
		    if( $media_id !== false ){
		        return array('media_id' => $media_id);
		    }
		    
			App::uses('CrawlUtility', 'Utility');
			$localfile = CrawlUtility::saveImagesByUrl($mediafile,'',array('oss'=>false,'resize'=>false));
			if( !$localfile ) {
				return array('errcode' => -1,'errmsg' => '封面图片下载错误，图片不要太大，使用可用的图片外链');
			}
			$is_remote = true;
			$mediafile = UPLOAD_FILE_PATH.$localfile;
			$mediafile = str_replace('//','/',$mediafile);
		}
		else{
		    if(!file_exists($mediafile)) {
                return array('errcode' => -1,'errmsg' => '封面图片网址错误');
            }
        }
		
		$i = 0;
		do{
		    $batch_url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token='.$access_token.'&type='.$type;
		    $response =  RequestFacade::post($batch_url,array('media'=> '@'.$mediafile,'type'=> $type ));
		    
		    $ret = \json_decode($response->body,true);

		    if($ret['media_id']) {
                if( $is_remote ){ //为远程文件时，删除下载的临时文件
                    @unlink($mediafile);
                }
		        if($cacke_key) {
		            Cache::write($cacke_key, $ret['media_id'],'long');
		        }
		        return $ret;
		    }
		    elseif($ret['errcode']){ //有错误码时，直接返回错误内容。 其它未知问题及网络原因时，重试。
                if( $is_remote ){ //为远程文件时，删除下载的临时文件
                    @unlink($mediafile);
                }
		        return $ret;
		    }
		    else{
		        CakeLog::error( "wechat add_material $mediafile try $i error. $src_media: ".var_export($response,true) );
		    }
		    $i++;
		}
		while( empty($ret['media_id'])  && !isset($ret['errcode']) && $i < 2); // 若上传失败，最多重试2次
		
		return $ret;
	}
	
	public static function del_material($media_id) {
	    if(empty($access_token)){
	        $access_token = self::getAccessToken();
	    }
	    $url = 'https://api.weixin.qq.com/cgi-bin/material/del_material?access_token='.$access_token;
	    $params = json_encode( array('media_id'=>$media_id) );
	    $response =  RequestFacade::post($url,$params);
	    return \json_decode($response->body,true);
	}
	
	public static function getImageMediaUrl($media_id){
	    $result = self::batchget_material('image');
	    foreach($result['item'] as $image){
	        if($image['media_id'] == $media_id) {
	            return $image['url'];
	        }
	    }
	}
	/**
	 * 批量获取多媒体素材
	 * @param string $type 素材的类型，图片（image）、视频（video）、语音 （voice）、图文（news）
	 * @param number $page 从全部素材的该偏移位置开始返回，0表示从第一个素材 返回
	 * @param number $limit 返回素材的数量，取值在1到20之间
	 */
	public static function batchget_material($type = 'news',$page=1,$limit = 20){
		if(empty($access_token)){
			$access_token = self::getAccessToken();
		}
		$url = 'https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token='.$access_token;
		$params = json_encode(array('type'=>$type,'offset'=>($page-1)*$limit,'count'=>$limit));
		$response =  RequestFacade::post($url,$params);
		return \json_decode($response->body,true);
	}
	
    /**
     * 上传图文消息内的图片获取URL
	 * 本接口所上传的图片不占用公众号的素材库中图片数量的5000个的限制。
	 * 图片仅支持jpg/png格式，大小必须在1MB以下。
	 */
    public static function uploadImg($filepath,$access_token = '') {
    	if(empty($access_token)){
    		$access_token = self::getAccessToken();    		
    	}
    	
    	if(empty($access_token)){
    		return array('errcode'=>111,'errmsg'=>'empty access token. The appid:'.self::$appId);
    	}
    	else{
        	$upload_url = 'https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token='.$access_token;
        	$i = 0;
        	do{
        	    if( $i > 0 ) usleep(100);
         	    $response =  RequestFacade::post($upload_url,array('media' => '@'.$filepath));
        	    //{"url":  "xxx"}
        	    $ret = \json_decode($response->body,true);
        	    $i++;
        	}
        	while( empty($ret['url']) && !isset($ret['errcode']) && $i < 2 );
        	
        	if( $ret['url'] ) {
        	    $ret['url'] = str_replace('http://mmbiz.qpic.cn','https://mmbiz.qlogo.cn',$ret['url']);
        	}
        	else{
        	    CakeLog::error( 'wechat uploadimg error,'.$filepath.': '.var_export($ret,true));
        	}
        	return $ret;
    	}
    }

    
	/**
	 * 新增临时素材
	 */
    public static function uploadMedia($filepath,$type='image',$access_token = '') { //分别有图片（image）、语音（voice）、视频（video）和缩略图（thumb）
    	if(empty($access_token)){
    		$access_token = self::getAccessToken();
    	}
    	$upload_url = sprintf(self::$upload_url,$access_token,$type);
    	$response =  RequestFacade::post($upload_url,array('media' => '@'.$filepath));
    	return \json_decode($response->body,true);
    }
    
    /**
     * 获取公众号的给定用户信息
     * @param string $openid
     */
    public static function getUserInfo($openid = '',$access_token = ''){
    	if(empty($access_token)){
    		$access_token = self::getAccessToken();
    	}
    	$userinfo_url = sprintf(self::$userinfo_url,$access_token,$openid);
    	$response =  RequestFacade::get($userinfo_url);
    	return \json_decode($response->body,true);
    }
    /**
     * 批量获取公众号的用户信息
     * @param string $openid
     */
    public static function getBatUserInfo($openids = array(),$access_token = ''){
        if(empty($access_token)){
            $access_token = self::getAccessToken();
        }
        
        $userinfo_url = 'https://api.weixin.qq.com/cgi-bin/user/info/batchget?access_token='.$access_token;
        $user_list = array();
        foreach($openids as $oid) {
            $user_list[] = array('openid' => $oid);
        }
        $response =  RequestFacade::post($userinfo_url,json_encode(array('user_list'=>$user_list)));
        return \json_decode($response->body,true);
    }
    
    
    public static function getJsApiTicket(){
        
        $cacheKey = 'wx_js_ticket_'.self::$appId;
        $data = Cache::read($cacheKey);
        
        if ( !is_object($data) || is_object($data) && $data->expire_time < time()) {
            $access_token = self::getAccessToken();
            // 如果是企业号用以下 URL 获取 ticket
            // $url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=$accessToken";
            $url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?type=jsapi&access_token=$access_token";
            $response =  RequestFacade::get($url);
            
            //CakeLog::info("js api result:".$response->body);
            if($response) {
                $res = \json_decode($response->body);
                if( empty($res) || empty($res->ticket) ) {
                    return false;
                }
                else{
                    $ticket = $res->ticket;
                    if ($ticket) {
                        $data = new Object();
                        $data->expire_time = time() + 7000;
                        $data->jsapi_ticket = $ticket;
                        Cache::write($cacheKey, $data);
                    }
                }
            }
            else{
                return false;
            }
        } else {
            $ticket = $data->jsapi_ticket;
        }
        
        return $ticket;
    }
    
    /**
     * 获取公众号的用户列表
     * @param string $next_openid
     */
    public static function getUserList($next_openid = '',$access_token = ''){
    	if(empty($access_token)){
    		$access_token = self::getAccessToken();  
    	}    	
    	$user_url = sprintf(self::$user_url,$access_token,$next_openid);
    	$response =  RequestFacade::get($user_url);
    	return \json_decode($response->body,true);
    }
    
    /**
     * 获取微信的access_token
     * @param string $force 是否不使用缓存，强制获取
     * @return string 
     */
	public static function getAccessToken($force=false,$dev=false){
		//if(empty(self::$appId)) self::$appId = Configure::read("Weixin.AppId");
		//if(empty(self::$secretKey)) self::$secretKey = Configure::read("Weixin.AppSecret");
// 取消session的调用，防止超时阻塞session。上传文件接口调用前先关闭session		
// 	    if(empty(self::$appId)) {
// 	        $wxinfo = CakeSession::read('User.wxinfo');
// 	        self::$appId = $wxinfo['Wx']['oauth_appid']; 
// 	    }
	    if( empty(self::$appId) ) {
// 	        CakeLog::error( 'GetAccessToken empty appId.Url:'.Router::url().'.Auth.User:'.var_export(CakeSession::read('Auth.User'),true).' $_REQUEST:'.var_export($_REQUEST,true));
	        return null;
	    }
	    
	    /* 开发者模式配置，微信也效验IP了。用户配置的无法正常工作
	    if( $dev && self::$secretKey ){ // 配置了开发模式的公众号，优先使用开发者模式的接口
	        $cacheKey = 'wx_app_token_'.self::$appId;
	        $token = Cache::read($cacheKey);
	        if( empty($token) || $force ){
	    
	            $i = 0;
	            do{
	                $url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".self::$appId."&secret=".self::$secretKey;
	                $response = RequestFacade::get($url);
	                $ret = \json_decode($response,true);
	                $i++;
	                if(empty($ret['errcode'])) {
	                    break;
	                }
	                else{
	                    CakeLog::error('get access_token error'.$response);
                    }
	            }while($i < 2);
	    
	            $token = $ret['access_token'];
	            Cache::write($cacheKey,$token,'default',6000);
	        }
	        return $token;
	    }*/

	    { //非开发者模式或开发者模式配置异常的
			// 直接通过公众号授权的公众号
			$obj = loadModelObject('Oauthbind');
			$oauthbind = $obj->find('first',array(
					'conditions' => array('source'=>'wechatComp','oauth_openid' => self::$appId),
			));
			
			if( !empty($oauthbind) ){
			    
			    if( $oauthbind['Oauthbind']['updated'] < time() - 7100 ) {
    			    $refresh_result = WeixinCompUtility::refreshToken($oauthbind['Oauthbind']['oauth_openid'],$oauthbind['Oauthbind']['refresh_token']);
    			    if(empty($refresh_result)) { // 网络原因未取得结果，跳过不处理。下次继续请求
    			        usleep(300); // 暂停200毫秒
    			        $refresh_result = WeixinCompUtility::refreshToken($oauthbind['Oauthbind']['oauth_openid'],$oauthbind['Oauthbind']['refresh_token']);
    			    }
    			    
    			    if(empty($refresh_result['errcode']) && !empty($refresh_result['authorizer_access_token'])){
    			        $obj->updateAll(array(
    			            'oauth_token' => $obj->escape_string($refresh_result['authorizer_access_token']),
    			            'expires' => $refresh_result['expires_in'],
    			            'refresh_token' => $obj->escape_string($refresh_result['authorizer_refresh_token']),
    			            'updated' => time(),
    			        ),array('id' => $oauthbind['Oauthbind']['id']));
    			        
    			        return $refresh_result['authorizer_access_token'];
    			    }
			    }
			    else if( $oauthbind['Oauthbind']['oauth_token'] ) {
			        return $oauthbind['Oauthbind']['oauth_token'];
			    }
			}
	    }
		return null;
	}
	
	private static function unicode_decode($name,$charset = 'UTF-8'){//GBK,UTF-8,big5
		$pattern = '/\\\u[\w]{4}/i';
		preg_match_all($pattern, $name, $matches);
		//print_r($matches);exit;
		if (! empty ( $matches )) {
			//$name = '';
			for($j = 0; $j < count ( $matches [0] ); $j ++) {
				$str = $matches [0] [$j];
				if (strpos ( $str, '\u' ) === 0) {
					$code = base_convert ( substr ( $str, 2, 2 ), 16, 10 );
					$code2 = base_convert ( substr ( $str, 4 ), 16, 10 );
					$c = chr ( $code ) . chr ( $code2 );
					if ($charset == 'GBK') {
						$c = iconv ( 'UCS-2BE', 'GBK', $c );
					} elseif ($charset == 'UTF-8') {
						$c = iconv ( 'UCS-2BE', 'UTF-8', $c );
					} elseif ($charset == 'BIG5') {
						$c = iconv ( 'UCS-2BE', 'BIG5', $c );
					} else {
						$c = iconv ( 'UCS-2BE', $charset, $c );
					}
					//$name .= $c;
					$name = str_replace($str,$c,$name);
				}
				//else {
				//	$name .= $str;
				//}
			}
		}
		return $name;
	}

}
